import { _decorator, Component, Node, Color, Graphics, UITransform, Vec3, Camera, find, Canvas } from 'cc';
import { GlobalEventBus } from '../core/EventBus';
import { EnemyRegistry } from '../gameplay/EnemyRegistry';
import { Clock } from '../core/Clock';
import { TICK_RATES } from '../shared';

const { ccclass, property } = _decorator;

interface Tracked {
  id: string;
  node: Node;
  ui: Node;
  gfx: Graphics;
  color: Color;
  width: number;
  height: number;
}

@ccclass('VisualOverlay')
export class VisualOverlay extends Component {
  @property
  public playerWidth = 28;

  @property
  public playerHeight = 46;

  @property
  public enemyWidth = 28;

  @property
  public enemyHeight = 46;

  private tracked = new Map<string, Tracked>();
  private unsubscribers: Array<() => void> = [];
  private uiTransform: UITransform | null = null;
  private camera: Camera | null = null;
  private clock: Clock | null = null;
  private clockKey = '';
  private screenPos = new Vec3();

  init(sceneRoot: Node, player: Node, clock: Clock) {
    this.uiTransform = this.getComponent(UITransform);
    // 尝试从 Canvas 获取渲染相机（UI/主相机复用皆可）
    const canvas = this.getComponent(Canvas) ?? find('Canvas')?.getComponent(Canvas) ?? null;
    this.camera = canvas?.cameraComponent ?? find('Canvas/Camera')?.getComponent(Camera) ?? null;
    this.clock = clock;
    this.clockKey = `visual-overlay-${this.node.uuid}`;
    this.clock.register(this.clockKey, TICK_RATES.render, () => this.updateOverlay());

    // Track player directly
    this.track('player', player, Color.BLUE, this.playerWidth, this.playerHeight);

    // Track existing enemies
    for (const [id, enemy] of EnemyRegistry.entries()) {
      if (enemy.node?.isValid) {
        this.track(id, enemy.node, Color.RED, this.enemyWidth, this.enemyHeight);
      }
    }

    // Subscribe to spawns and deaths
    this.unsubscribers.push(
      GlobalEventBus.on('entity/spawn', (p) => {
        if (p.kind === 'enemy') {
          const e = EnemyRegistry.get(p.id);
          if (e && e.node?.isValid) {
            this.track(p.id, e.node, Color.RED, this.enemyWidth, this.enemyHeight);
          }
        }
      }),
    );
    this.unsubscribers.push(
      GlobalEventBus.on('entity/die', (p) => {
        this.untrack(p.id);
      }),
    );

    if (typeof console !== 'undefined' && console.debug) {
      console.debug('[VISUAL] overlay initialized');
    }
  }

  onDisable() {
    for (const u of this.unsubscribers) u();
    this.unsubscribers = [];
    for (const t of Array.from(this.tracked.values())) {
      t.ui.destroy();
    }
    this.tracked.clear();
    this.clock?.unregister(this.clockKey);
  }

  private track(id: string, node: Node, color: Color, w: number, h: number) {
    if (this.tracked.has(id)) return;
    const ui = new Node(`oval_${id}`);
    const gfx = ui.addComponent(Graphics);
    const ut = ui.addComponent(UITransform);
    ut.setContentSize(w, h);
    ut.setAnchorPoint(0.5, 0.5);
    this.node.addChild(ui);
    this.tracked.set(id, { id, node, ui, gfx, color, width: w, height: h });
    this.drawEllipse(gfx, color, w, h);
  }

  private untrack(id: string) {
    const t = this.tracked.get(id);
    if (!t) return;
    t.ui.destroy();
    this.tracked.delete(id);
  }

  private drawEllipse(gfx: Graphics, color: Color, w: number, h: number) {
    gfx.clear();
    gfx.fillColor = color;
    gfx.ellipse(0, 0, w / 2, h / 2);
    gfx.fill();
  }

  private updateOverlay() {
    if (!this.uiTransform || !this.camera) return;
    const out = new Vec3();
    for (const t of this.tracked.values()) {
      if (!t.node?.isValid) continue;
      // 将3D世界坐标 -> 屏幕坐标 -> 转为 Canvas 本地坐标
      this.camera.worldToScreen(t.node.worldPosition, this.screenPos);
      this.uiTransform.convertToNodeSpaceAR(this.screenPos, out);
      t.ui.setPosition(out);
    }
  }
}

export default VisualOverlay;
